#!/usr/bin/env python
# -*- coding: utf-8 -*-

from fastapi import APIRouter, status, Request, Header
from fastapi import Depends, HTTPException

from models.crud import *
from models.schemas import UserToken
from datetime import timedelta, datetime
from jose import JWTError, jwt
from typing import Optional

from . import create_db
from models.utils import *


# SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
# ALGORITHM = "HS256"
# ACCESS_TOKEN_EXPIRE_MINUTES = 30


user_router = APIRouter()






def create_access_token(data: dict, expires: Optional[timedelta] = None):
    """创建jwt"""
    to_encode = data.copy()
    if expires:
        expire_time = datetime.now() + expires
    else:
        expire_time = datetime.now() + timedelta(minutes=30)
    to_encode.update({"exp": expire_time})
    encode_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encode_jwt


async def get_current_user(request: Request, token: Optional[str] = Header(...)) -> BaseUser:
    """token依赖请求头的token校验"""
    # 验证失败返回信息
    credentials_exc = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Authentication Failed",
        headers={"WWW-Authenticate": "Bearer"}
    )
    # 未登录返回信息
    not_login_exc = HTTPException(
        status_code=status.HTTP_403_FORBIDDEN,
        detail="NOT LOGIN OR TOKEN EXPIRED"
    )
    try:
        # 解析token
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username = payload.get("sub")
        if username is None:
            raise credentials_exc
        # 从redis获取用户token
        redis_token = await request.app.state.redis.get(username)
        if not redis_token or redis_token != token:
            raise not_login_exc
        return BaseUser(email=username)
    except JWTError:
        raise credentials_exc




@user_router.get("/users", response_model=List[UserOut])
def get_users(skip: int = 0, limit: int = 10, db:Session=Depends(create_db)):
    return get_users_method(db, skip, limit)


@user_router.post("/users", response_model=UserOut)
def create_user(user: UserModel, db: Session = Depends(create_db)):
    return create_user_method(db, user)


# @user_router.get("/users/{uid}", response_model=UserOut)
# def get_user(uid:int, db:Session=Depends(create_db)):
#     return get_user_method(db, uid)


# 获取用户信息接口，需要先校验是否登陆(请求Header中带token)
@user_router.get("/user", response_model=UserOut)
def get_user(user: BaseUser = Depends(get_current_user), db: Session = Depends(create_db)):
    return get_user_by_email(db, user.email)






@user_router.post("/login")
async def login(request: Request, user: UserModel, db: Session = Depends(create_db)):
    db_user = get_user_by_email(db, user.email)
    # 密码校验
    verify = verify_password(user.password, db_user.hashed_password)
    if verify:
        # 产生token
        token = create_access_token(data={"sub": user.email})
        is_cached = await request.app.state.redis.get(user.email)
        if is_cached:
            raise HTTPException(status_code=200, detail="请勿重复登录")
        await request.app.state.redis.set(user.email, token, expire=ACCESS_TOKEN_EXPIRE_MINUTES*60)
        user_token = UserToken(token=token, email=user.email)
        return user_token
    else:
        raise HTTPException(status_code=200, detail="用户名或密码错误")